import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// 格子类 >> 原始类
class xxxSquare extends React.Component {
  constructor(props) {
    super(props);
    // this.state = {
    //   value: null
    // }
  }

  render() {
    return (
      <button
        className="square"
        onClick={() => this.props.onClick()}
      >
        {this.props.value}
      </button>
    )
  }
}

// 格子类 >> 重写：函数组件方式
function Square(props) {
  return (
    <button
      className="square"
      onClick={props.onClick}
    >
      {props.value}
    </button>
  )
}

// 棋盘类
class Board extends React.Component {
  // constructor(props) {
  //   super(props);
  //   this.state = {
  //     // 集中状态管理，把格子的所有数据存储在这个数组中 9 个
  //     squares: Array(9).fill(null),
  //     // 下一步是否为 X，默认先手棋子为 X
  //     xIsNext: true
  //   }
  // }

  // handleClick(i) {
  //   // slice() 创建一个新的数组对象返回
  //   const originSquares = this.state.squares.slice();

  //   // 异常处理: 1. 当前格子已经被填充 2. 已经出现赢家
  //   if (originSquares[i] || calculateWinner(originSquares)) {
  //     console.log("停止...");
  //     return;
  //   }

  //   const isX = this.state.xIsNext;
  //   originSquares[i] = isX ? "X" : "O";
  //   this.setState({
  //     squares: originSquares,
  //     xIsNext: !isX
  //   })
  // }

  // 渲染格子的函数
  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        onClick={() => this.props.onClick(i)}
      />
    )
  }

  render() {
    // let status;
    // const winner = calculateWinner(this.state.squares);
    // if (winner) {
    //   // 有赢家
    //   status = `Winner：${winner}`;
    // } else {
    //   // 无赢家
    //   status = `Next player：${this.state.xIsNext ? "X" : "O"}`;
    // }
    return (
      <div>
        {/* <div className="status">{this.props.status}</div> */}
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    )
  }
}

// 游戏控制类
class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null)
      }],
      xIsNext: true,
      // 当前正在查看哪一项历史记录，默认第一项
      stepNumber: 0
    }
  }

  handleClick(i) {
    // 当我们回到历史每个节点时，重新下棋 slice 能帮助我们把错误的未来节点丢弃掉，重新开始...
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const historyLen = history.length;
    const current = history[historyLen - 1];
    const squares = current.squares.slice();

    if (squares[i] || calculateWinner(squares)) { return; }

    const isX = this.state.xIsNext;
    squares[i] = isX ? "X" : "O";
    this.setState({
      history: history.concat([{ squares: squares }]),
      xIsNext: !isX,
      // 更新当前游戏步骤
      stepNumber: historyLen
    })
  }

  jumpTo(index) {
    this.setState({
      stepNumber: index,
      // 0 % 2 === 0 true X
      // 1 % 2 === 0 false O
      // ...
      xIsNext: (index % 2) === 0
    })
  }

  render() {
    let status;
    const history = this.state.history;
    // 根据当前 stepNumber 渲染
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    const moves = history.map((item, index) => {
      const desc = index ? `Go to move ${index}` : 'Go to game start';
      return (
        <li key={index}>
          <button onClick={() => this.jumpTo(index)}>{desc}</button>
        </li>
      )
    })

    if (winner) {
      status = `Winner：${winner}`;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }
    return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
        </div>

        <div className="game-info">
          <div>{status}</div>
          <div>{moves}</div>
        </div>
      </div>
    )
  }
}

/**
 * 计算赢家: 井字棋玩法一共 8 种赢的组合，我们把每种可能的组合下标放到一个数组，所有组合用一个大的数组包起来，这样就变成了一个多维数组
 * @param {Array} squares 存储当前所有格子状态的数组
 * @returns "X" "O" null
 */
function calculateWinner(squares) {
  const winnerList = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ];
  // 先存储起来，避免 for 循环时重复读取
  const len = winnerList.length;
  for (let i = 0; i < len; i++) {
    // 数组解构: 对应下标的变量赋值
    const [a, b, c] = winnerList[i];
    if (squares[a] && squares[a] == squares[b] && squares[b] == squares[c]) {
      // 某一个玩家赢了: 返回这个玩家
      return squares[a];
    }
  }
  // 没有玩家胜利: 返回 null
  return null;
}

// 页面渲染

ReactDOM.render(
  <Game />,
  document.getElementById('root')
);